const testMode = false; // 为true时可以在浏览器打开不报错
// vscode webview 网页和普通网页的唯一区别：多了一个acquireVsCodeApi方法
const vscode = testMode ? {} : acquireVsCodeApi();
const callbacks = {};

/**
 * 调用vscode原生api，
 * @param data 可以是类似 {cmd: 'xxx', param1: 'xxx'}，也可以直接是 cmd 字符串
 * @param cb 回调函数
 */
function callVscode(data, cb) {
    if (typeof data === 'string') {
        data = { cmd: data };
    }
    if (cb) {
        // 时间戳加上5位随机数
        const cbid = Date.now() + '' + Math.round(Math.random() * 100000);
        callbacks[cbid] = cb;
        data.cbid = cbid;
    }
    vscode.postMessage(data);
}

window.addEventListener('message', event => {
    const message = event.data;
    switch (message.cmd) {
        case 'vscodeCallback':
            console.log(message.data);
            (callbacks[message.cbid] || function () { })(message.data);
            delete callbacks[message.cbid];
            break;
        default: break;
    }
});
const emptyKey = '__EMPTY_KEY__';

new Vue({
    el: '#app',
    data: {
        projectName: '加载中',
        params: {
            env: 'daily',
            appname: '',
            serviceName: '',
        },
        // 添加service弹窗参数列表
        addParams: {
        },
        loading: false,
        // 根数据
        proxy: {
            services: []
        },
        allDataList: [],
        dataList: [],
        editItem: {
            item: null,
            subitem: null,
            version: '',
            serviceKey: '',
        },
        depAppname: '',
        depList: [],
        methodList: [],
        methodModal: {
            serviceNameAndVersion: '',
            loading: false,
        },
        autoRunProxy: false,
    },
    mounted() {
        callVscode('getProjectName', projectName => this.projectName = projectName);
        this.initList();
    },
    watch: {
        'addParams.env'(nv, ov) {
            this.refreshServiceList();
        },
        'params.autoRunProxy'(nv, ov) {
            if (nv) {
                this.alert('自动run proxy功能有待完善！');
            }
        }
    },
    methods: {
        // 模拟alert
        alert(info) {
            callVscode({ cmd: 'alert', info: info }, null);
        },
        // 弹出错误提示
        error(info) {
            callVscode({ cmd: 'error', info: info }, null);
        },
        waiting() {
            this.alert('功能有待完善，敬请期待！');
        },
        // 初始化整个列表
        initList() {
            this.loading = true;
            this.proxy = {
                services: []
            };
            if (testMode) {
                this.initTestList();
                return;
            }
            callVscode({ cmd: 'getAllProxy' }, proxy => {
                const defaultGroup = proxy.group || 'HSF';
                // 按照appname排序
                proxy.services.sort((a, b) => a.appname === b.appname ? 0 : (a.appname < b.appname ? -1 : 1));
                proxy.services.forEach(service => {
                    for (let key in service.api) {
                        if (typeof service.api[key] === 'string') {
                            service.api[key] = {
                                // 从string转过来的，为了保存时最小化修改，启用一个字段标识一下
                                __fromString: true,
                                interfaceName: service.api[key],
                                group: defaultGroup
                            }
                        }
                        service.api[key].edit = false;
                        service.api[key].show = true;
                    }
                    service.edit = false;
                    service.show = true;
                });
                this.proxy = proxy;
                this.loading = false;
            });
        },
        // 顶部筛选项查询
        query() {
            this.proxy.services.forEach(service => {
                service.show = !this.params.appname || service.appname === this.params.appname;
                for (let item in service.api) {
                    service.api[item].show = !this.params.serviceName || service.api[item].interfaceName.toLowerCase().indexOf(this.params.serviceName.trim().toLowerCase()) >= 0;
                }
            });
        },
        // 获取第一个show为true的行索引
        getFirstShowIdx(service) {
            let i = 0;
            for (let item in service.api) {
                if (service.api[item].show) return i;
                i++;
            }
            return i;
        },
        // 添加service
        addService() {
            this.addParams = {
                env: this.params.env, // 复制默认环境配置
                loading: false,
                artLoading: false,
                depLoading: false,
                errorInfo: '',
                artErrorInfo: '',
                depErrorInfo: '',
                hsfVersionList: [],
                depVersionList: {},
                serviceName: '',
                version: '',
                appname: '',
                group: '',
                artifactId: '',
                groupId: '',
                dependencyVersion: '',
            };
            $('#modal_add_service').modal('show');
            setTimeout(() => {
                this.$refs.modal_service_name.focus();
            }, 50);
            callVscode({cmd: 'addGoldLog', key: 'addService'}, null);
        },
        refreshServiceList() {
            if (!this.addParams.serviceName.trim()) return;
            this.addParams.loading = true;
            this.addParams.errorInfo = '';
            let params = {
                cmd: 'getHsfVersionList',
                env: this.addParams.env,
                serviceName: this.addParams.serviceName.trim()
            };
            callVscode(params, resp => {
                this.addParams.loading = false;
                if (resp.code === 0) {
                    this.addParams.hsfVersionList = resp.data;
                    if (resp.data.length) {
                        const item = resp.data[0]; // 默认选中第一个
                        this.addParams.version = item.version;
                        this.addParams.appname = item.appname;
                        this.addParams.group = item.group;
                        this.addParams.artLoading = true;
                        this.addParams.artErrorInfo = '';
                        let params = {
                            cmd: 'getArtifactId',
                            serviceNameAndVersion: item.serviceNameAndVersion,
                            env: this.addParams.env
                        };
                        callVscode(params, resp => {
                            this.addParams.artLoading = false;
                            if (resp.code === 0) {
                                this.addParams.artifactId = resp.data;
                                this.refreshDependencyInfo();
                            } else if (resp.code === 601) {
                                this.addParams.artErrorInfo = '自动推测失败，请手动填写';
                            }
                        });
                    }
                } else if (resp.code === 600) {
                    this.addParams.errorInfo = '服务不存在';
                }
            });
        },
        // 刷新依赖信息
        refreshDependencyInfo() {
            this.addParams.depLoading = true;
            this.addParams.depErrorInfo = '';
            callVscode({ cmd: 'getDependencyInfo', artifactId: this.addParams.artifactId }, resp => {
                this.addParams.depLoading = false;
                if (resp.code === 0) {
                    this.addParams.groupId = resp.data.groupId;
                    const depVersionList = {};
                    depVersionList[resp.data.latestRelease] = resp.data.latestRelease + '（release）';
                    depVersionList[resp.data.latestSnapshot] = resp.data.latestSnapshot + '（snapshot）';
                    this.addParams.depVersionList = depVersionList;
                    this.addParams.dependencyVersion = resp.data.latestRelease; // 默认选中release版本
                } else if (resp.code === 600) {
                    this.addParams.depErrorInfo = resp.message;
                }
            });
        },
        // 添加service确认
        submitAddService() {
            const keyMap = {}, serviceMap = {}, depMap = {}, appMap = {};
            const params = this.addParams;
            params.serviceName = params.serviceName.trim();
            this.proxy.services.forEach(service => {
                appMap[service.appname] = service;
                for (let key in service.api) {
                    keyMap[key] = service.api[key];
                    serviceMap[service.api[key].interfaceName] = service.appname;
                }
                service.dependency.forEach(dep => {
                    depMap[`${dep.groupId}-${dep.artifactId}`] = dep;
                });
            });
            if (serviceMap[params.serviceName]) {
                this.alert(`service已存在于${serviceMap[params.serviceName]}中，请勿重复添加！`);
                return;
            }
            const temp = params.serviceName.split('.');
            let serviceKey = temp[temp.length - 1];
            if (keyMap[serviceKey]) {
                serviceKey += '2'; // 重名就加一个2
            }
            let target = null;
            if (appMap[params.appname]) {
                target = appMap[params.appname];
            } else {
                target = {
                    appname: params.appname,
                    api: {},
                    dependency: []
                };
                this.proxy.services.push(target);
            }
            target.version = params.version; // 覆盖HSF版本
            this.$set(target.api, serviceKey, {
                interfaceName: params.serviceName,
                group: params.group,
                edit: false,
                show: true,
            });
            // 当前appname下的依赖映射
            const currentDepMap = {};
            target.dependency.forEach(dep => {
                currentDepMap[`${dep.groupId}-${dep.artifactId}`] = dep;
            })
            const depKey = `${params.groupId}-${params.artifactId}`
            if (depMap[depKey] && !currentDepMap[depKey]) {
                return;
            }
            if (currentDepMap[depKey]) {
                currentDepMap[depKey].version = params.dependencyVersion;
            }
            if (!depMap[depKey] && !currentDepMap[depKey]) {
                target.dependency.push({
                    groupId: params.groupId,
                    artifactId: params.artifactId,
                    version: params.dependencyVersion
                });
            }
            this.saveAll();
            $('#modal_add_service').modal('hide');
        },
        // 编辑
        editService(item, subitem, serviceKey) {
            // 每次最多编辑一行
            if (this.editItem.item) {
                this.editItem.item.edit = false;
                this.editItem.subitem.edit = false;
            }
            item.edit = true;
            subitem.edit = true;
            this.editItem.item = item;
            this.editItem.subitem = subitem;
            this.editItem.serviceKey = serviceKey;
            let params = {
                cmd: 'getHsfVersionList',
                env: this.params.env,
                serviceName: subitem.interfaceName
            };
            callVscode(params, resp => {
                if (resp.code === 0) {
                    item.hsfVersionList = resp.data;
                    // 默认选中
                    this.editItem.version = item.version;
                }
            });
        },
        submitEditService(item, api, serviceKey) {
            item.version = this.editItem.version;
            // 如果修改了serviceKey
            if (this.editItem.serviceKey !== serviceKey) {
                this.$set(api, this.editItem.serviceKey, api[serviceKey]);
                this.$delete(api, serviceKey);
            }
            this.cancelEditService(item, api[this.editItem.serviceKey]);
            this.saveAll();
        },
        cancelEditService(item, subitem) {
            item.edit = false;
            subitem.edit = false;
            this.editItem.item = null;
            this.editItem.subitem = null;
        },
        deleteService(api, key) {
            this.$delete(api, key);
            if (Object.keys(api).length === 0) {
                this.$set(api, emptyKey, {});
            }
            this.saveAll();
        },
        // 保存全部
        saveAll() {
            const proxy = this.simpleDeepCopy(this.proxy);
            // 还原services
            proxy.services.forEach(service => {
                delete service.edit;
                delete service.show;
                delete service.hsfVersionList;
                for (let key in service.dependency) {
                    delete service.dependency[key].temp;
                }
                for (let key in service.api) {
                    delete service.api[key].edit;
                    delete service.api[key].show;
                    if (service.api[key].__fromString) {
                        // 还原成简单的字符串
                        service.api[key] = service.api[key].interfaceName;
                    }
                }
            });
            // 最后保存时重新排序一下
            proxy.services.sort((a, b) => a.appname === b.appname ? 0 : (a.appname < b.appname ? -1 : 1));
            callVscode({cmd: 'saveAll', proxy}, resp => {
                if (resp.code === 0) {
                    this.alert('保存成功！');
                }
            });
        },
        gotoServiceKey(item, text) {
            callVscode({cmd: 'openFileInVscode', path: `config/proxy-cfg/${item.appname}.js`, text});
        },
        openFileInVscode(dep) {
            callVscode({cmd: 'openFileInVscode', path: `assembly/lib/${dep.artifactId}-${dep.version}-sources.jar`});
        },
        openFileInFinder(dep) {
            callVscode({cmd: 'openFileInFinder', path: `assembly/lib/${dep.artifactId}-${dep.version}-sources.jar`});
        },
        openJarByJdGui(dep) {
            callVscode({cmd: 'openJarByJdGui', path: `assembly/lib/${dep.artifactId}-${dep.version}-sources.jar`});
        },
        showDepModal(item) {
            this.depAppname = item.appname;
            this.depList = item.dependency;
            $('#modal_dep_manage').modal('show');
        },
        // 编辑依赖
        editDep(dep) {
            this.$set(dep, 'temp', {
                groupId: dep.groupId,
                artifactId: dep.artifactId,
                version: dep.version,
                versionList: {}
            });
            callVscode({ cmd: 'getDependencyInfo', artifactId: dep.artifactId }, resp => {
                if (resp.code === 0) {
                    const versionList = {};
                    versionList[resp.data.latestRelease] = resp.data.latestRelease + '（release）';
                    versionList[resp.data.latestSnapshot] = resp.data.latestSnapshot + '（snapshot）';
                    dep.temp.versionList = versionList;
                } else if (resp.code === 600) {
                    this.error(resp.message);
                }
            });
        },
        submitEditDep(dep) {
            if (!dep.temp.groupId || !dep.temp.artifactId || !dep.temp.version) {
                this.error('参数不能为空！');
                return;
            }
            // 校验
            dep.groupId = dep.temp.groupId;
            dep.artifactId = dep.temp.artifactId;
            dep.version = dep.temp.version;
            dep.temp = null;
            this.saveAll();
        },
        deleteDep(idx) {
            this.depList.splice(idx, 0);
            this.saveAll();
        },
        showMethodModal(item, subitem) {
            const serviceNameAndVersion = `${subitem.interfaceName}:${item.version}`;
            this.methodModal.serviceNameAndVersion = serviceNameAndVersion;
            this.methodModal.loading = true;
            this.methodList = [];
            callVscode({cmd: 'getMethodList', serviceNameAndVersion, env: this.params.env}, resp => {
                this.methodModal.loading = false;
                if (resp.code === 0) {
                    this.methodList = resp.data.methods;
                }
            });
            $('#modal_method_list').modal('show');
        },
        copyServiceName() {
            /* new Clipboard('[data-clipboard-text]').on('success', e => {
                this.alert('复制到剪贴板成功！');
            }); */
        },
        // 方法测试
        methodTest(name, parameterTypes) {
            const host = this.getHsfHost(this.params.env == 'daily');
            const url = `http://${host}/hsfops/testpage/testMethod.htm?envType=${this.params.env}&service=${this.methodModal.serviceNameAndVersion}&method=${name}~${parameterTypes.join(';')}`;
            callVscode({cmd: 'openUrlInBrowser', url}, null);
        },
        // 方法压测
        methodYace(name, parameterTypes) {
            const url = `http://pas.${this.getAbnHost()}/hsftestcase?service=${this.methodModal.serviceNameAndVersion}&method=${name}`;
            callVscode({cmd: 'openUrlInBrowser', url}, null);
        },
        simpleDeepCopy(obj) {
            return JSON.parse(JSON.stringify(obj));
        },
        /**
         * 获取HSF域名
         */
        getHsfHost(isDaily) {
            const hostDaily = [23055, 23068372726, 30341];
            const hostOnline = [23055, 23068372726, -24168, 16438];
            return this.parseNumberHost(isDaily ? hostDaily : hostOnline);
        },
        getAbbHost() {
            return this.parseNumberHost([23068372726, -24168, 16438]);
        },
        getAbnHost() {
            return this.parseNumberHost([23068372726, 30341]);
        },
        /**
         * 解析数字域名
         * @param {*} arr 
         */
        parseNumberHost(arr) {
            return arr.map(num => `${num < 0 ? '-' : ''}${Math.abs(num).toString(36)}`).join('.').replace(/\.-/g, '-');
        },
        initTestList() {
            this.proxy = {
                services: [
                    {
                        appname: 'test',
                        dependency: [{ groupId: 'my'}],
                        children: [ { serviceKey: 'myService' }]
                    },
                    {
                        appname: 'aaa',
                        dependency: [{ groupId: 'bbb'}],
                        children: [{ serviceKey: 'myService222' }]
                    }
                ]
            };
        }
    }
});